﻿using Abp.Configuration.Startup;
using Abp.Runtime.Session;
using App.Authorization.Roles;
using App.Authorization.Users;
using App.BaseObject;
using App.Configuration;
using App.Configuration.Dto;
using App.WebApi.Models;
using App.WebApi.ViewModels;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Results;

namespace App.WebApi.Controllers
{
    public class SystemController : AppApiControllerBase
    {
        private readonly UserManager _userManager;

        private readonly ISettingsAppService _settingsService;
        private readonly ICommonAppService _commonService;
        private readonly IUserAppService _userService;
        private readonly IDictionaryAppService _dictionaryService;
        private readonly IRoleAppService _roleService;
        private readonly IMultiTenancyConfig _multiTenancyConfig;

        public SystemController(
            UserManager userManager,
            ISettingsAppService settingsService,
            ICommonAppService CommonService, 
            IUserAppService userService,
            IRoleAppService roleService,
            IDictionaryAppService dictionaryService,
            IMultiTenancyConfig multiTenancyConfig)
        {
            _userManager = userManager;
            _commonService = CommonService;
            _userService = userService;
            _dictionaryService = dictionaryService;
            _settingsService = settingsService;
            _roleService = roleService;
            _multiTenancyConfig = multiTenancyConfig;
        }

        [HttpGet]
        public async Task<HttpResponseMessage> Init()
        {
            var curUser = await _userService.GetUserById(AbpSession.UserId.Value);
            var userTenant = await _userManager.GetTenantById(curUser.TenantId);
            var initData = "var WebPlus = " + JsonConvert.SerializeObject(new
            {
                config = await _settingsService.GetAllSettings(),
                user = new
                {
                    TenantId = AbpSession.TenantId,
                    UserName = (_multiTenancyConfig.IsEnabled ? userTenant == null ? ".\\" : userTenant.TenancyName+ "\\" : "" )+ curUser.UserName,
                    curUser.Email,
                    curUser.Mobile,
                    LoginCount = await _userService.GetLoginCount(AbpSession.UserId.Value)
                },
                dictionarys = await GetDictionarys()
            });

            return new HttpResponseMessage { Content = new StringContent(initData, Encoding.GetEncoding("UTF-8"), "application/json") };
        }

        [HttpGet]
        public async Task<JsonResult<List<Button>>> GetAllButtons()
        {
            return Json(await _settingsService.GetAllButton());
        }

        public JsonResult<GridResult> GetButtons(int page, int rows, string sort = "CreationTime", string order = "asc", string filterRules = "")
        {
            int total;
            var where = "";

            var query = _commonService.GetPageRecords<Button>(where, page, rows, sort, order, out total,
                filterRules);

            return Json(new GridResult { total = total, rows = query });
        }

        public async Task<List<CalendarEventViewModel>> GetCalendarEventa(DateTime start, DateTime end)
        {
            var calendarEvents = await _userService.GetCalendarEvents(start, end);
            return calendarEvents.Select(s => new CalendarEventViewModel { Id = s.Id, Start = s.StartDate, End = s.EndDate, Title = s.Subject, Color = s.Color }).ToList();
        }

        public async Task<JsonResult<List<MenuTree>>> GetNavTrees()
        {
            var data = await _userService.GetAllMenuByUserId(AbpSession.GetUserId());

            var result = new List<MenuTree>();
            Recursion(new MenuTree { id = null, children = new List<MenuTree>() }, result, data);
            return Json(result);
        }

        public async Task<JsonResult<List<MenuTree>>> GetMenu()
        {
            var data = await _settingsService.GetAllMenuPermissions();
            var result = new List<MenuTree>();
            RecursionAll(new MenuTree { id = null, children = new List<MenuTree>() }, result, data);
            return Json(result);
        }

        public async Task<JsonResult<List<Role>>> GetRoles()
        {
            return Json(await _roleService.GetAllRole());
            
        }

        public async Task<JsonResult<List<Role>>> GetAllRoles()
        {
            return Json(await _roleService.GetAllRole());
        }

        #region Helpers
            //递归
        private void Recursion(MenuTree parentNode, IList<MenuTree> result, IList<MenuPermission> list)
        {
            foreach (var item in from c in list.OrderBy(s => s.SortOrder).OrderBy(s => s.CreationTime) where c.ParentId == parentNode.id && c.MenuType != "button" select c)
            {
                var buttons = list.Where(m => m.ParentId == item.Id && m.MenuType == "button").OrderBy(s => s.SortOrder).OrderBy(s => s.CreationTime).Select(s => new ButtonDto() { ButtonLink = s.MenuLink, ButtonName = s.MenuText, IconCls = s.IconCls, Id = s.Id }).ToList();
                var child = new MenuTree { id = item.Id, text = item.MenuText, ParentId = item.ParentId, MenuLink = item.MenuLink, MenuText = item.MenuText, Buttons = buttons, IconCls = item.IconCls, SortOrder = item.SortOrder, IsActivated=item.IsActivated, expanded = true, children = new List<MenuTree>() };
                if (item.ParentId == null)
                {
                    result.Add(child);
                }
                else
                {
                    child.leaf = true;
                    parentNode.children.Add(child);
                }
                Recursion(child, result, list);
            }
        }

        private void RecursionAll(MenuTree parentNode, IList<MenuTree> result, IList<MenuPermission> list)
        {
            foreach (var item in from c in list.OrderBy(s => s.SortOrder).OrderBy(s=>s.CreationTime) where c.ParentId == parentNode.id select c)
            {
                var buttons = list.Where(m => m.ParentId == item.Id && m.MenuType == "button").OrderBy(s => s.SortOrder).OrderBy(s => s.CreationTime).Select(s => new ButtonDto() { ButtonLink = s.MenuLink, ButtonName = s.MenuText, IconCls = s.IconCls, Id = s.Id }).ToList();
                var child = new MenuTree { id = item.Id, text = item.MenuText, ParentId = item.ParentId, MenuLink = item.MenuLink, MenuText = item.MenuText,Buttons=buttons,MenuType=item.MenuType, IconCls=item.IconCls, SortOrder = item.SortOrder, IsActivated = item.IsActivated, expanded = true, children = new List<MenuTree>() };
                if (item.ParentId == null)
                {
                    result.Add(child);
                }
                else
                {
                    child.leaf = true;
                    parentNode.children.Add(child);
                }
                RecursionAll(child, result, list);
            }
        }

        private string GetExiseField(PropertyInfo[] propertys) {
            foreach (var item in propertys)
            {
                DescriptionAttribute attr = Attribute.GetCustomAttribute(item,
                    typeof(DescriptionAttribute), false) as DescriptionAttribute;
                if (attr != null && attr.Description == "exise")
                {
                    return item.Name;
                }
            }

            return "";
        }

        private async Task<Dictionary<string, Dictionary<int, string>>> GetDictionarys()
        {
            var result = new Dictionary<string, Dictionary<int, string>>();
            foreach (var item in await _dictionaryService.GetAll())
            {
                if (string.IsNullOrEmpty(item.Dictionarys)) continue;
                result.Add(item.Key, GetDictionary(item.Dictionarys));
            }
            return result;
        }

        private Dictionary<int, string> GetDictionary(string dictionarys)
        {
            var result = new Dictionary<int, string>();
            var i = 0;
            foreach (var item in dictionarys.Split(','))
            {
                result.Add(i, item);
                i++;
            }
            return result;
        }
        #endregion
    }
}
